package com.vxdata.utils.modules.utils.zstp;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.util.StringUtil;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadCallback;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.io.FilenameUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class FastDFSFileUtil {
    /**
     * FastDFS 安装教程: https://blog.csdn.net/qq_40942490/article/details/110182615
     */
    @Resource
    private FastFileStorageClient fastFileStorageClient;

    public String upload(MultipartFile file) throws IOException {
        String fileExtension = FilenameUtils.getExtension(file.getOriginalFilename());
        try (InputStream inputStream = file.getInputStream()) {
            StorePath storePath = fastFileStorageClient.uploadFile(inputStream, file.getSize(), fileExtension, null);
            return storePath.getFullPath();
        }
    }

    public void delete(String path) {
        fastFileStorageClient.deleteFile(path);
    }

    public void download(String fileUrl, HttpServletResponse response) throws IOException {
        String group = fileUrl.substring(0, fileUrl.indexOf("/"));
        String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
        DownloadByteArray downloadByteArray = new DownloadByteArray();
        byte[] bytes = fastFileStorageClient.downloadFile(group, path, downloadByteArray);
        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileUrl, "UTF-8"));
        response.setCharacterEncoding("UTF-8");
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            outputStream.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 下载文件到本地
     *
     * @param fileUrl       fastDFS path  group1/M00/00/00/wKgKeGXVvL6AMGwbAAAAZHRO8MM06.json
     * @param localFilePath 本地路径 C:\Users\33067\Desktop\group1/M00/00/00/wKgKeGXVvL6AMGwbAAAAZHRO8MM06.json
     * @throws IOException
     */
    public void downloadToLocal(String fileUrl, String localFilePath) throws IOException {
        String group = fileUrl.substring(0, fileUrl.indexOf("/"));
        String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
        DownloadByteArray downloadByteArray = new DownloadByteArray();
        byte[] bytes = fastFileStorageClient.downloadFile(group, path, downloadByteArray);

        // 将字节数组写入到本地文件
        try (OutputStream outputStream = new FileOutputStream(localFilePath)) {
            outputStream.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
            throw new IOException("写入文件失败");
        }
    }

    /**
     * 读取文件内容
     *
     * @param path
     * @return
     */
    public String readFileContentAsyncToString(String path, String encoding) {
        try {
            // 解析 path 获取组名和文件路径
            StorePath storePath = StorePath.parseFromUrl(path);

            // 异步下载文件内容
            return fastFileStorageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadCallback<String>() {
                @Override
                public String recv(InputStream inputStream) throws IOException {
                    // 将文件内容读取到字符串中
                    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, encoding));
                    StringBuilder contentBuilder = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        contentBuilder.append(line);
                        contentBuilder.append("\n");
                    }
                    return contentBuilder.toString();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("无法读取该类型文件");
        }
    }

    /**
     * 按行读取文件内容
     *
     * @param vo 配置信息
     * @return
     */
    public List<Map<String, Object>> readFileContentAsyncToMap(ReadFileVo vo) {
        try {
            // 解析 path 获取组名和文件路径
            StorePath storePath = StorePath.parseFromUrl(vo.getPath());
            // 异步下载文件内容
            return fastFileStorageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadCallback<List<Map<String, Object>>>() {
                @Override
                public List<Map<String, Object>> recv(InputStream inputStream) throws IOException {
                    // 将文件内容读取到字符串中
                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, vo.getEncoding()))) {
                        // csv 文件
                        if (getExtension(vo.getPath()).equalsIgnoreCase("csv")) {
                            return LargeCsvReadUtil.readCsvMapList(reader, vo.getContentIdList(), vo.getContentColName(), vo.getFieldDelimiter());
                        }
                        // 非csv文件
                        else {
                            String content = LargeFileReadUtil.readFile(reader);
                            Map<String, Object> map = new LinkedHashMap<>();
                            map.put("key", 1);
                            map.put("value", content);
                            return Collections.singletonList(map);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException("无法读取该类型文件");
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("无法读取该类型文件");
        }

    }


    /**
     * 读取文件字段列表
     */
    public List<String> readColList(String path, String encoding) {
        String extension = getExtension(path);
        switch (extension) {
            case "csv":
                return readColListFromCsv(path, encoding);
            case "json":
                return readColListFromJson(path, encoding);
            default:
                return null;
        }
    }

    /**
     * 读取文件字段列表-csv
     */
    private List<String> readColListFromCsv(String path, String encoding) {
        try {
            // 解析 path 获取组名和文件路径
            StorePath storePath = StorePath.parseFromUrl(path);
            // 异步下载文件内容
            return fastFileStorageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadCallback<List<String>>() {
                @Override
                public List<String> recv(InputStream inputStream) throws IOException {
                    // 将文件内容读取到字符串中
                    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, encoding));
                    String headerLine = reader.readLine();
                    List<String> headerList = Arrays.asList(headerLine.split(","));
                    // 去除每个元素两边的双引号和单引号
                    List<String> cleanedList = headerList.stream()
                            .map(str -> str.replaceAll("^['\"]|['\"]$", ""))
                            .collect(Collectors.toList());
                    return cleanedList;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("无法读取该类型文件");
        }
    }

    /**
     * 读取文件字段列表-json
     */
    private List<String> readColListFromJson(String jsonFile, String encoding) {
        String jsonStr = readFileContentAsyncToString(jsonFile, encoding);
        if (StringUtil.isNotEmpty(jsonStr)) {
            TreeMap<String, String> jsonColMap = JsonParserUtil.analysisJson(jsonStr);
            if (CollectionUtil.isNotEmpty(jsonColMap)) {
                Set<String> set = jsonColMap.keySet();
                Set<String> cleanedSet = set.stream()
                        .map(str -> str.replaceAll("^['\"]|['\"]$", "")) // 去除每个元素两边的双引号和单引号
                        .collect(Collectors.toSet());
                return new ArrayList<>(cleanedSet);
            }
        }
        return null;
    }


    /**
     * 获取文件后缀
     */
    private static String getExtension(String path) {
        int lastDotIndex = path.lastIndexOf('.');
        // 后缀名
        String extension = lastDotIndex != -1 ? path.substring(lastDotIndex + 1) : "";
        // 转小写
        extension = extension.toLowerCase();
        return extension;
    }

}
